package com.xgy.userauthsystem.service;

import com.xgy.userauthsystem.entity.User;
import com.xgy.userauthsystem.exception.*;
import com.xgy.userauthsystem.mapper.UserMapper;
import com.xgy.userauthsystem.util.EmailApi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * 用户服务类
 * 处理用户注册、登录等业务逻辑
 */
@Service
@Transactional
public class UserService {

    private static final Logger logger = LoggerFactory.getLogger(UserService.class);

    private final UserMapper userMapper;//数据访问接口
    private final CaptchaService captchaService;//验证码服务
    private final EmailApi emailApi;//邮件发送服务
    private final StringRedisTemplate redisTemplate;//Redis缓存模板

    // 密码验证正则表达式：至少6位，包含字母和数字
    private static final String PASSWORD_PATTERN = "^(?=.*[A-Za-z])(?=.*\\d).{6,}$";
    private static final Pattern pattern = Pattern.compile(PASSWORD_PATTERN);
    
    // 邮箱验证码缓存前缀和有效期（分钟）
    private static final String EMAIL_CODE_PREFIX = "email_code:";
    private static final long EMAIL_CODE_EXPIRE_MINUTES = 5;

    // 构造函数注入依赖
    @Autowired
    public UserService(UserMapper userMapper, CaptchaService captchaService, EmailApi emailApi, StringRedisTemplate redisTemplate) {
        this.userMapper = userMapper;
        this.captchaService = captchaService;
        this.emailApi = emailApi;
        this.redisTemplate = redisTemplate;
    }

    /**
     * 用户注册
     * @param user 用户对象
     * @param captchaId 验证码ID
     * @param captchaInput 用户输入的验证码
     * @return 注册成功的用户
     * @throws UsernameAlreadyExistsException 用户名已存在异常
     * @throws EmailAlreadyExistsException 邮箱已存在异常
     * @throws InvalidPasswordException 密码无效异常
     */
    public User register(User user, String captchaId, String captchaInput) {
        logger.info("开始用户注册流程，用户名: {}", user.getUsername());

        // 验证验证码
        if (!captchaService.validateCaptcha(captchaId, captchaInput)) {
            logger.warn("验证码验证失败: captchaId={}, input={}", captchaId, captchaInput);
            throw new InvalidCaptchaException("验证码错误或已过期");
        }

        // 检查用户名是否已存在
        if (userMapper.existsByUsername(user.getUsername())) {
            logger.warn("用户名已存在: {}", user.getUsername());
            throw new UsernameAlreadyExistsException(
                    "用户名 '" + user.getUsername() + "' 已被使用，请选择其他用户名"
            );
        }

        // 检查邮箱是否已存在
        if (userMapper.existsByEmail(user.getEmail())) {
            logger.warn("邮箱已存在: {}", user.getEmail());
            throw new EmailAlreadyExistsException(
                    "邮箱 '" + user.getEmail() + "' 已被使用，请使用其他邮箱"
            );
        }

        // 验证密码强度
        if (!isValidPassword(user.getPassword())) {
            logger.warn("密码不符合要求: {}", user.getPassword());
            throw new InvalidPasswordException(
                    "密码必须至少6位，且包含字母和数字"
            );
        }

        // 保存用户
        int result = userMapper.insert(user);
        if (result == 0) {
            logger.error("用户注册失败，数据库插入返回0行受影响，用户名: {}", user.getUsername());
            throw new RuntimeException("用户注册失败");
        }
        logger.info("用户注册成功: {}", user.getUsername());

        return user;
    }

    /**
     * 用户登录
     * @param username 用户名
     * @param password 密码
     * @return 登录成功的用户
     * @throws InvalidLoginException 登录无效异常
     */
    @Transactional(readOnly = true)
    public User login(String username, String password) {
        logger.info("用户尝试登录: {}", username);

        try {
            // 查找用户
            User user = userMapper.findByUsername(username);
            if (user == null) {
            logger.warn("登录失败：用户名不存在: {}", username);
            throw new InvalidLoginException("用户名或密码错误");
        }

            // 验证密码
            if (!user.getPassword().equals(password)) {
                logger.warn("登录失败：密码错误，用户名: {}", username);
                throw new InvalidLoginException("用户名或密码错误");
            }

            logger.info("用户登录成功: {}", username);
            return user;

        } catch (InvalidLoginException e) {
            // 重新抛出业务异常
            throw e;
        } catch (Exception e) {
            // 记录其他异常并包装
            logger.error("登录过程中发生系统错误，用户名: {}", username, e);
            throw new InvalidLoginException("登录过程中发生错误，请稍后重试", e);
        }
    }

    /**
     * 发送邮箱验证码
     * @param email 用户邮箱
     * @throws EmailNotFoundException 邮箱不存在异常
     */
    public void sendEmailCode(String email) {
        logger.info("开始发送邮箱验证码，邮箱: {}", email);

        // 检查邮箱是否存在
        if (!userMapper.existsByEmail(email)) {
            logger.warn("邮箱不存在: {}", email);
            throw new EmailNotFoundException("该邮箱未注册");
        }

        // 生成6位随机数字验证码
        String code = String.format("%06d", (int) (Math.random() * 1000000));
        
        // 存储到Redis，设置过期时间
        String key = EMAIL_CODE_PREFIX + email;
        redisTemplate.opsForValue().set(key, code, EMAIL_CODE_EXPIRE_MINUTES, TimeUnit.MINUTES);
        
        // 发送邮件
        String subject = "用户认证系统验证码";
        String content = "您的验证码是: " + code + "，有效期为" + EMAIL_CODE_EXPIRE_MINUTES + "分钟。";
        boolean success = emailApi.sendGeneralEmail(subject, content, email);
        
        if (success) {
            logger.info("邮箱验证码发送成功，邮箱: {}", email);
        } else {
            logger.error("邮箱验证码发送失败，邮箱: {}", email);
            throw new RuntimeException("验证码发送失败");
        }
    }

    /**
     * 邮箱验证码登录
     * @param email 用户邮箱
     * @param code 验证码
     * @return 登录成功的用户
     * @throws EmailNotFoundException 邮箱不存在异常
     * @throws EmailCodeExpiredException 验证码过期异常
     * @throws EmailCodeIncorrectException 验证码错误异常
     */
    @Transactional(readOnly = true)
    public User emailLogin(String email, String code) {
        logger.info("用户尝试邮箱验证码登录: {}", email);

        // 检查邮箱是否存在
        User user = userMapper.findByEmail(email);
        if (user == null) {
            logger.warn("登录失败：邮箱不存在: {}", email);
            throw new EmailNotFoundException("该邮箱未注册");
        }

        // 从Redis获取验证码
        String key = EMAIL_CODE_PREFIX + email;
        String storedCode = redisTemplate.opsForValue().get(key);
        
        // 检查验证码是否存在
        if (storedCode == null) {
            logger.warn("登录失败：验证码已过期，邮箱: {}", email);
            throw new EmailCodeExpiredException("验证码已过期，请重新获取");
        }
        
        // 验证验证码是否正确
        if (!storedCode.equals(code)) {
            logger.warn("登录失败：验证码错误，邮箱: {}", email);
            throw new EmailCodeIncorrectException("验证码错误");
        }
        
        // 删除已使用的验证码
        redisTemplate.delete(key);
        
        logger.info("用户邮箱验证码登录成功: {}", email);
        return user;
    }

    /**
     * 验证密码强度
     * 密码必须至少6个字符，包含字母和数字
     * @param password 密码
     * @return 如果密码符合要求返回true，否则返回false
     */
    private boolean isValidPassword(String password) {
        if (password == null || password.trim().isEmpty()) {
            return false;
        }
        return pattern.matcher(password).matches();
    }
}